package com.study.sequence.service.impl;

import com.study.sequence.common.CommonConstract;
import com.study.sequence.common.FlushService;
import com.study.sequence.common.SequenceDTO;
import com.study.sequence.service.ISequenceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by 张波 on 2020/5/23.
 */
@Slf4j
@Service
public class ISequecneServiceImpl implements ISequenceService {

    @Autowired
    private FlushService flushService;

    private static final Map<String, SequenceDTO> SEQUENCE_DTO_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>(8);

    private static final ReentrantLock LOCK = new ReentrantLock();

    @Override
    public String getSequence() {
        return getSequence(CommonConstract.DEFAULT_BUSINESS_KEY);
    }

    @Override
    public String getSequence(String businessKey) {
        if (SEQUENCE_DTO_CONCURRENT_HASH_MAP.containsKey(businessKey)) {
            return SEQUENCE_DTO_CONCURRENT_HASH_MAP.get(businessKey).getSequence();
        }
        return initSequence(businessKey);
    }

    private String initSequence(String businessKey) {
        try {
            LOCK.lock();
            if (!SEQUENCE_DTO_CONCURRENT_HASH_MAP.containsKey(businessKey)) {
                log.info("开始初始化sequence序列，businessKey:{}", businessKey);
                StopWatch stopWatch = new StopWatch();
                stopWatch.start();
                SequenceDTO sequenceDTO = flushService.init(businessKey);
                stopWatch.stop();
                SEQUENCE_DTO_CONCURRENT_HASH_MAP.put(businessKey, sequenceDTO);
                log.info("序列初始化完成，businessKey:{}，本次耗时：{}ms", businessKey, stopWatch.getTime());
                /*第一为0的舍弃*/
                String sequence = sequenceDTO.getSequence();
                if (StringUtils.isBlank(sequence)) {
                    throw new RuntimeException("初始获取序列号异常:businessKey:" + businessKey + ",sequence:" + sequence);
                }
                return sequenceDTO.getSequence();
            } else {
                return SEQUENCE_DTO_CONCURRENT_HASH_MAP.get(businessKey).getSequence();
            }
        } finally {
            LOCK.unlock();
        }
    }


}
